#include <stdio.h>
#include "bsp_wifi.h"
#include "ota.h"
#include "audio_sr.h"
#include "bsp_sound.h"
#include "audio_encoder.h"
#include "audio_decoder.h"
#include "ws.h"
#include "display.h"
// abc
// abcd by dev
// abcd by dev2
// abcd by dev3
// abcd by dev4
// abcd by dev5
// abcd by dev6
// abcd by dev6 asadfa
typedef enum
{
    APP_IDLE,
    APP_CONNECTING,
    APP_SPEAKING,
    APP_LISTENING
} app_state_t;

// 应用状态
static app_state_t app_state = APP_IDLE;

typedef struct
{
    RingbufHandle_t sr_2_encoder;
    RingbufHandle_t encoder_2_ws;
    RingbufHandle_t ws_2_decoder;

    EventGroupHandle_t eg;
} my_app_t;
my_app_t my_app;

void wifi_succ(void);
void wifi_fail(void);
void create_ringbuf(void);
void wake_cb(void);
void vad_change_cb(vad_state_t state);

void text_cb(char *, int);
void bin_cb(char *, int);
void close_cb(void);

void audio_upload_task(void *);
void app_main(void)
{
    // 显示初始化
    display_init();
    // 初始化wifi
    bsp_wifi_init();
    bsp_wifi_start(wifi_succ, wifi_fail);

    while(1)
    {
        vTaskDelay(10);
    }
}

// 音频编解码器测试任务
void test(void *args)
{
    while(1)
    {
        size_t size;
        void  *data = xRingbufferReceive(my_app.encoder_2_ws, &size, portMAX_DELAY);

        xRingbufferSend(my_app.ws_2_decoder, data, size, portMAX_DELAY);

        vRingbufferReturnItem(my_app.encoder_2_ws, data);
    }
}

void wifi_succ(void)
{
    my_app.eg = xEventGroupCreate();

    // printf("wifi connect succ\n");
    //  1. ota 检测: 主要获取激活码和ws的地址
    ota_check_version();

    // 2. 初始硬件音频编解码器
    bsp_sound_init();
    bsp_sound_open();

    // 3. 创建需要的环形缓冲区
    create_ringbuf();

    // 4. 初始化sr
    audio_sr_init();
    audio_sr_start(my_app.sr_2_encoder, wake_cb, vad_change_cb);

    // 5. 初始化并启动 音频编解码器
    audio_encoder_init();
    audio_encoder_start(my_app.sr_2_encoder, my_app.encoder_2_ws);

    audio_decoder_init();
    audio_decoder_start(my_app.ws_2_decoder);

    // 6. 初始化websocket客户端
    ws_init(text_cb, bin_cb, close_cb);

    // 7. 创建一个任务,上传音频
    xTaskCreate(audio_upload_task, "audio_upload_task", 4096, NULL, 5, NULL);

    display_show_tts("说:\"你好,小智\", 开始与小智进行对话");

    // 创建一个测试音频编解码器的任务
    // xTaskCreate(test, "test", 4096, NULL, 5, NULL);
}

void create_ringbuf(void)
{
    my_app.sr_2_encoder = xRingbufferCreateWithCaps(16 * 1024,
                                                    RINGBUF_TYPE_BYTEBUF,   // 必须是bytebuf
                                                    MALLOC_CAP_SPIRAM);

    my_app.encoder_2_ws = xRingbufferCreateWithCaps(16 * 1024,
                                                    RINGBUF_TYPE_NOSPLIT,   //
                                                    MALLOC_CAP_SPIRAM);
    my_app.ws_2_decoder = xRingbufferCreateWithCaps(32 * 1024,
                                                    RINGBUF_TYPE_NOSPLIT,   //
                                                    MALLOC_CAP_SPIRAM);
}

void wake_cb(void)
{
    MY_LOGE("wake");
    switch(app_state)
    {
        case APP_IDLE:
        {
            if(!my_ws.is_connected)
            {
                app_state = APP_CONNECTING;
                ws_open_audio_channel();

                ws_send_hello();
                // 等待hello响应完成
                xEventGroupWaitBits(my_app.eg, 1 << 0, true, true, portMAX_DELAY);
            }

            break;
        }
        case APP_SPEAKING:
        {
            // 发送中指信息
            ws_send_abort();
            break;
        }
        default:
            break;
    }

    app_state = APP_IDLE;
    // 发送唤醒词 TODO
    ws_send_wake();
}
void vad_change_cb(vad_state_t state)
{
    // MY_LOGE("change: %s", state == VAD_SPEECH ? "speech" : "silence");
    if(state == VAD_SPEECH && app_state != APP_SPEAKING)   // 人在说话, 小智没有在说话
    {
        app_state = APP_LISTENING;
        ws_send_start_listening();
    }
    else if(state == VAD_SILENCE && app_state == APP_LISTENING)
    {
        app_state = APP_IDLE;
        ws_send_stop_listening();
    }
}

void text_cb(char *txt, int len)
{
    cJSON *root = cJSON_ParseWithLength(txt, len);
    if(root == NULL)
    {
        MY_LOGE("parse json error");
        cJSON_Delete(root);
        return;
    }

    cJSON *typeItem = cJSON_GetObjectItem(root, "type");
    if(typeItem == NULL)
    {
        MY_LOGE("type item error");
        cJSON_Delete(root);
        return;
    }
    MY_LOGI("%.*s", len, txt);
    if(strcmp(typeItem->valuestring, "hello") == 0)
    {
        MY_LOGI("收到hello信息");
        xEventGroupSetBits(my_app.eg, 1 << 0);

        ws_send_iot_descriptor();
        ws_send_iot_state();
    }
    else if(strcmp(typeItem->valuestring, "tts") == 0)   // tts == text to speech
    {
        cJSON *stateItem = cJSON_GetObjectItem(root, "state");
        if(stateItem == NULL)
        {
            MY_LOGE("state item error");
            cJSON_Delete(root);
            return;
        }
        if(strcmp(stateItem->valuestring, "sentence_start") == 0)
        {
            app_state       = APP_SPEAKING;
            cJSON *textItem = cJSON_GetObjectItem(root, "text");
            if(textItem)
            {
                char *text = textItem->valuestring;
                display_show_tts(text);
            }
        }
        else if(strcmp(stateItem->valuestring, "sentence_end") == 0)
        {
            app_state = APP_IDLE;
        }
    }
    else if(strcmp(typeItem->valuestring, "iot") == 0)
    {
        cJSON *commandsItem = cJSON_GetObjectItem(root, "commands");
        cJSON *commandItem  = cJSON_GetArrayItem(commandsItem, 0);
        char  *method       = cJSON_GetObjectItem(commandItem, "method")->valuestring;
        cJSON *parms        = cJSON_GetObjectItem(commandItem, "parameters");

        if(strcmp(method, "SetVolume") == 0)
        {
            int vol = cJSON_GetObjectItem(parms, "volume")->valueint;

            // 调用函数
            setVolume(vol);
        }
        else if(strcmp(method, "SetMute") == 0)
        {
            cJSON *muteItem = cJSON_GetObjectItem(parms, "mute");
            bool   mute     = false;
            if(cJSON_IsBool(muteItem))
            {
                mute = cJSON_IsTrue(muteItem);
            }
            setMute(mute);
        }
    }
    else if(strcmp(typeItem->valuestring, "llm") == 0)   // tts == text to speech
    {
        cJSON *textItem = cJSON_GetObjectItem(root, "emotion");
        if(textItem)
        {
            char *text = textItem->valuestring;
            display_show_llm(text);
        }
    }
}
void bin_cb(char *bin, int len)
{
    audio_decoder_write(bin, len);
}
void close_cb(void)
{
    // 把状态变长非唤醒
    my_sr.is_wake = false;
}

void audio_upload_task(void *args)
{
    while(1)
    {
        size_t size = 0;

        void *data = xRingbufferReceive(my_app.encoder_2_ws, &size, portMAX_DELAY);
        if(app_state == APP_LISTENING && data && size > 0)
        {
            ws_send_bin(data, size);
        }
        vRingbufferReturnItem(my_app.encoder_2_ws, data);
    }
}

void wifi_fail(void)
{
    printf("wifi connect fail\n");
}
